import NIM from './NIM_Web_NIM_weixin.js'
import { getGlobalData, setGlobalData } from '../configuration/globaldata'
import { createWYAccountRequest, updateWYinfoRequest } from '../service/im-controller'
import {
  notDeletedPostSessionRequest,
  postMessageDeletedByUserIdRequest
} from '../service/post-controller'
import { showToast } from '../crossplatform/apiservice/toast'
import { getDateDiff, calcTimeHeader } from './lodashmin/formatDate'
import { showTabBarRedDot, hideTabBarRedDot } from '../crossplatform/apiservice/tabbar'
import { getStore } from '../store/index'
import { UPDATEIM } from '../store/types/im'
import judgeBlack from './judge_black'

// store
const store = getStore()
store.subscribe(handleUserInfoChange)
function handleUserInfoChange() {
  const { userinfo, im } = store.getState()
  IMController.props = { ...userinfo, ...im }
}

const imId = getGlobalData('IM_ID')

const IMData = getGlobalData('IMData')

let nim = getGlobalData('nim')

const IMController = {
  queryWrap: () => {
    return new Promise(resolve => {
      const {
        userId,
        role,
        userInfoC,
        userInfoB,
        companyName,
        companyId,
        mobile
      } = IMController.props
      if (userId) {
        let userInfo = role == 'personal' ? { ...userInfoC } : { ...userInfoB }
        let userData = IMController.dealMineUserInfo({
          userId,
          role,
          userInfo,
          companyName,
          ex: {
            companyId
          },
          mobile
        })
        IMController.updateImState({
          contactList: [],
          sessions: []
        })

        IMController.createWYAccount(userData).then(() => {
          const { accid, token } = userData
          // 获取nim实例
          if (Object.keys(nim).length) {
            IMController.destroy().then(() => {
              IMController.getInstance({ accid, token })
            })
          } else {
            IMController.getInstance({ accid, token })
          }

          IMController.updateImState({
            loginInfo: userData
          })

          let timer = setTimeout(() => {
            // 更新用户信息
            clearTimeout(timer)
            IMController.updateMyInfo({ userId, role, userInfo, companyName, companyId })
            role === 'company' && IMController.notDeletedPostSession(userId)
            role === 'company' && judgeBlack.getBlackCompanyIds(companyId)
          }, 500)

          resolve()
        })
      } else {
        resolve()
      }
    })
  },
  updateImState(payload) {
    store.dispatch({
      type: UPDATEIM,
      payload: {
        ...payload
      }
    })
  },
  getInstance: ({ accid, token }) => {
    nim = NIM.getInstance({
      // 是否开启日志, 开发者可以开启日志, 这样 SDK 会将关键操作的信息打印到控制台上, 便于调试
      debug: false,
      appKey: IMData.appKey,
      account: accid,
      token: token,
      promise: true,
      transports: ['websocket'],
      syncSessionUnread: true, // 同步未读数
      onconnect: IMController.onConnect,
      onwillreconnect: IMController.onWillReconnect,
      ondisconnect: IMController.onDisconnect,
      onerror: IMController.onError,
      onmsg: IMController.onMsg,
      // 会话
      onsessions: IMController.onSessions,
      onupdatesession: IMController.onUpdateSession
    })

    setGlobalData('nim', nim)
  },
  onConnect: () => {
    console.log('连接成功')
  },
  onWillReconnect: obj => {
    // 此时说明 SDK 已经断开连接, 请开发者在界面上提示用户连接已断开, 而且正在重新建立连接
    console.log('即将重连')
    console.log(obj.retryCount)
    console.log(obj.duration)
  },
  onDisconnect: error => {
    // 此时说明 SDK 处于断开状态, 开发者此时应该根据错误码提示相应的错误信息, 并且跳转到登录页面
    console.log('丢失连接')
    console.log(error)
    if (error) {
      switch (error.code) {
        // 账号或者密码错误, 请跳转到登录页面并提示错误
        case 302:
          break
        // 重复登录, 已经在其它端登录了, 请跳转到登录页面并提示错误
        case 417:
          break
        // 被踢, 请提示错误后跳转到登录页面
        case 'kicked':
          break
        default:
          break
      }
    }
  },
  onError: error => {
    console.log(error)
  },
  onMsg: msg => {
    // console.log('收到消息', msg.scene, msg.type, msg)
    IMController.pushMsg(msg, true)
    switch (msg.type) {
      case 'custom':
        IMController.onCustomMsg(msg)
        break
      case 'notification':
        // 处理群通知消息
        break
      // 其它case
      default:
        break
    }
  },
  onSessions: sessions => {
    console.log('onSessions: ', sessions)
    IMController.updateSessions(sessions)
    IMController.checkRedDot(sessions)
  },
  onUpdateSession: session => {
    console.log('会话更新了', session)
    const { sessions: sessionsOld, currentSessionId } = IMController.props
    IMController.updateSessions(nim.mergeSessions(sessionsOld, [session]))
    if (session.unread && currentSessionId) {
      IMController.updateUnreadInfo(currentSessionId)
    }
  },
  updateSessions: sessions => {
    // 更新数据
    if (!Array.isArray(sessions)) {
      sessions = [sessions]
    }
    IMController.dealSessions(sessions).then(users => {
      if (users) {
        let newSession = []
        users.map((item, index) => {
          let thisSession = sessions[index]
          const { lastMsg = {}, unread, updateTime } = thisSession
          newSession.push({
            account: item.account,
            nick: item.nick,
            sign: item.sign,
            lastMsg: lastMsg.type === 'image' ? '[图片]' : lastMsg.text,
            type: lastMsg.type,
            unread,
            msgTime: getDateDiff(updateTime),
            avatarUrl: item.avatar,
            gender: item.gender
          })
          return item
        })
        IMController.updateImState({
          contactList: [...newSession],
          sessions
        })
      }
    })
    IMController.checkRedDot(sessions)
  },
  updateUnreadInfo: currentSessionId => {
    // 更新当前会话的未读消息
    if (currentSessionId) nim.resetSessionUnread(currentSessionId)
  },
  dealMineUserInfo: ({ userId, role, userInfo, companyName, ex, mobile }) => {
    // 处理用户信息
    userId = (userId && parseInt(userId)) || 0
    let gender = userInfo.gender || userInfo.sex
    const { isOld } = userInfo
    let accid = role == 'personal' ? userId + 'c' + imId : userId + 'b' + imId
    isOld ? (accid = accid + 'old') : null
    const userData = {
      accid,
      birth: userInfo.gmtBirth && userInfo.gmtBirth.split('-')[0],
      gender: gender === 'female' ? 2 : 1,
      icon: userInfo.userAvator,
      mobile: userInfo.mobile || mobile,
      name: userInfo.userName,
      sign: role == 'personal' ? '' : companyName,
      ex: JSON.stringify(ex),
      token: '007'
    }
    return userData
  },
  pushMsg: (msgs, isReceive) => {
    if (!Array.isArray(msgs)) {
      msgs = [msgs]
    }
    // 存储数据到store
    const { msgArray } = IMController.props
    let newMsgArray = msgArray && msgArray.length ? [...msgArray] : []
    let imMsgArray = [...newMsgArray, ...IMController.dealMsgModal(msgs)]
    if (isReceive) {
      IMController.updateImState({
        msgArray: imMsgArray,
        toView: `chat${imMsgArray.length - 1}`
      })
    } else {
      IMController.updateImState({
        msgArray: imMsgArray
      })
    }
  },
  onCustomMsg: msg => {
    // 处理自定义消息
  },
  destroy: () => {
    // im 退出登录
    return new Promise(resolve => {
      nim.destroy({
        done: () => {
          console.log('destroy really done!')
          resolve()
        }
      })
    })
  },
  sendMsg: ({ selToID, value }) => {
    return new Promise(resolve => {
      // 发送消息
      let msg = nim.sendText({
        scene: 'p2p',
        to: selToID,
        text: value,
        done: (err, msgNew) => {
          // 判断错误类型，并做相应处理
          if (IMController.handleErrorAfterSend(err)) {
            IMController.sendMsg({ selToID, value })
            return
          }
          console.log('正在发送p2p text消息, id=' + msg.idClient)
          IMController.pushMsg(msg)
          resolve(true)
        }
      })
    })
  },
  createAccount: ({ userId, role, userInfo, companyName = '', companyId = '' }) => {
    return new Promise(resolve => {
      IMController.getUser(userId).then(noUser => {
        if (noUser) {
          // 有这个用户 直接跳转
          IMController.updateImState({
            selToID: userId,
            msgArray: []
          })
          IMController.updateMyInfo({ userId, role, userInfo, companyName, companyId })
          resolve()
        } else {
          // 没有这个用户
          const userData = IMController.dealMineUserInfo({
            userId,
            role,
            userInfo,
            companyName,
            ex: { companyId }
          })
          IMController.createWYAccount(userData).then(() => {
            IMController.updateImState({
              selToID: userId,
              msgArray: []
            })
            resolve()
          })
        }
      })
    })
  },
  getUser: id => {
    // 获取单个信息
    return new Promise(resolve => {
      if (Object.keys(nim).length) {
        nim.getUser({
          sync: true,
          account: id,
          done: (error, users) => {
            if (!error) {
              console.log('收到用户资料列表', users)
              // data.users = nim.mergeUsers(data.users, users)
              resolve(users)
            } else {
              resolve(false)
            }
          }
        })
      } else {
        resolve(false)
      }
    })
  },
  getUsers: (ids = []) => {
    // 获取多个信息
    return new Promise(resolve => {
      nim.getUsers({
        sync: true,
        accounts: ids,
        done: (error, users) => {
          if (!error) {
            console.log('收到用户资料列表', users)
            // data.users = nim.mergeUsers(data.users, users)
            resolve(users)
          } else {
            resolve(false)
          }
        }
      })
    })
  },
  updateMyInfo: ({ userId, role, userInfo, companyName = '', companyId }) => {
    // 更新用户信息
    let userData = IMController.dealMineUserInfo({
      userId,
      role,
      userInfo,
      companyName,
      ex: { companyId }
    })
    if(userData.name) {
      return updateWYinfoRequest(userData)
    } else {
      return ''
    }
  },
  createWYAccount: wyAccountModel => {
    return new Promise(resolve => {
      if (wyAccountModel.accid) {
        createWYAccountRequest(wyAccountModel).then(({ message }) => {
          if (message && message !== 'already register') {
            showToast({
              title: message || '创建用户失败'
            })
          }
          resolve()
        })
      } else {
        resolve()
      }
    })
  },
  dealMsgModal: msgs => {
    const { role, userId } = IMController.props
    if (!Array.isArray(msgs)) {
      msgs = [msgs]
    }
    let newMsgs = []
    msgs.map(item => {
      const pushJson =
      item && item.displayTimeHeader
        ? {
          type: item.type,
          from: item.from,
          to: item.to,
          isSelf:
            role == 'personal'
              ? item.from == userId + 'c' + imId
              : item.from == userId + 'b' + imId,
          time: item.time,
          displayTimeHeader: item.displayTimeHeader
        }
        : {
          type: item.type,
          from: item.from,
          to: item.to,
          isSelf:
            role == 'personal'
              ? item.from == userId + 'c' + imId
              : item.from == userId + 'b' + imId,
          time: item.time
        }
      switch (item.type) {
        case 'text':
          pushJson.value = item.text
          break
        case 'image':
          const { w, h, url } = item.file
          pushJson.value = url
          pushJson.width = w
          pushJson.height = h
          break
        default:
          pushJson.value = item.text
          break
      }
      newMsgs.push(pushJson)
      return item
    })
    return newMsgs
  },
  handleErrorAfterSend: err => {
    /**
     * 统一发送消息后打回的错误信息
     * 返回true表示有错误，false表示没错误
     */
    if (err) {
      if (err.code == 7101) {
        showToast({
          title: '你已被对方拉黑'
        })
      }
      showToast({
        title: err
      })
      console.log(err)
      return true
    }
    return false
  },
  getHistoryMsgs: ({ selToID, maxCnt, lastMsgTime }) => {
    // 获取云端历史记录
    return new Promise(resolve => {
      nim.getHistoryMsgs({
        scene: 'p2p',
        to: selToID,
        limit: maxCnt,
        asc: true, // 时间正序排序
        endTime: lastMsgTime,
        done: (err, obj) => {
          let complete = false
          if (err) {
            console.log(err)
            showToast({
              title: '请检查网络后重试'
            })
            return
          }
          // 所有历史消息加载完毕
          if (obj.msgs.length < maxCnt) {
            complete = true
          }
          if (obj.msgs.length) {
            // 如果有历史消息
            let reMsgArray = IMController.reCalcAllMessageTime(obj.msgs)
            let newMsgs = []
            newMsgs = IMController.dealMsgModal(reMsgArray)
            obj.msgs = newMsgs
          }
          resolve({ obj, complete })
        }
      })
    })
  },
  delChat: ({ toId }) => {
    //删除单条服务器上的会话
    return new Promise(resolve => {
      nim.deleteSession({
        scene: 'p2p',
        to: toId,
        done: (error, obj) => {
          resolve()
        }
      })
    })
  },
  deleteSessions: ({ sessions = [] }) => {
    // 批量删除服务器上的会话
    // 格式： [{ scene: 'p2p', to: 'account' }, { scene: 'p2p', to: 'account1' }]
    return new Promise(resolve => {
      nim.deleteSessions({
        sessions,
        done: (error, obj) => {
          if (!error) {
            // 删除消息成功
            resolve(obj)
          } else {
            return IMController.deleteSessions({ sessions })
          }
        }
      })
    })
  },
  dealSessions: sessions => {
    // 处理session数据
    if (!Array.isArray(sessions)) {
      sessions = [sessions]
    }
    let ids = []
    sessions.map(item => {
      ids.push(item.id.split('-')[1])
      return item
    })
    return IMController.getUsers(ids)
  },
  checkRedDot: sessions => {
    // tabbar是否展示红点
    let isRed = false
    if (!Array.isArray(sessions)) {
      sessions = [sessions]
    }
    sessions.map(item => {
      if (item.unread) {
        isRed = true
      }
    })
    if (isRed) {
      showTabBarRedDot({
        index: 1
      })
    } else {
      hideTabBarRedDot({
        index: 1
      })
    }
  },
  reCalcAllMessageTime: tempArr => {
    // 重新计算时间头
    if (tempArr.length == 0) return
    // 计算时差
    tempArr.map((msg, index) => {
      if (index === 0) {
        msg['displayTimeHeader'] = calcTimeHeader(msg.time)
      } else {
        let delta = (msg.time - tempArr[index - 1].time) / (120 * 1000)
        if (delta > 1) {
          // 距离上一条，超过两分钟重新计算头部
          msg['displayTimeHeader'] = calcTimeHeader(msg.time)
        }
      }
    })
    return tempArr
  },
  notDeletedPostSession: userId => {
    // 获取发布岗位后 未删除完成的会话
    notDeletedPostSessionRequest({ userId }).then(({ data }) => {
      const { code, data: entry, message } = data
      if (code === 200) {
        if (entry) {
          // 格式： [{ scene: 'p2p', to: 'account' }, { scene: 'p2p', to: 'account1' }]
          let sessions = []
          let userIdArr = entry.split(',')
          userIdArr.map(item => {
            sessions.push({
              scene: 'p2p',
              to: `${item}c${imId}`
            })
            return item
          })
          IMController.deleteSessions({ sessions }).then(status => {
            if (status) {
              // 删除消息成功 通知后端
              postMessageDeletedByUserIdRequest({ userId })
            } else {
              showToast({
                title: '消息失败~'
              })
            }
          })
        }
      }
    })
  }
}
export default IMController
